Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit e64b36ddad646270267ec466e9546e01321ebc57


Parents : f0f5bb1
Author : Ivan <e46112d44649266d71fe2193e00a4710>
Signature : T66BB85Valid, signed by author
Date : 2026-07-19T05:25:25-05:00

feat: improve LinkUtils to support NomadNet backtick field parameters and improve link rendering in tests

Changes
Diff

diff --git a/meshchatx.rsm b/meshchatx.rsm
index 8ace4ccf..a574accc 100644
Binary files a/meshchatx.rsm and b/meshchatx.rsm differ

diff --git a/meshchatx/src/frontend/js/LinkUtils.js b/meshchatx/src/frontend/js/LinkUtils.js
index abbe2e6e..a444e194 100644
--- a/meshchatx/src/frontend/js/LinkUtils.js
+++ b/meshchatx/src/frontend/js/LinkUtils.js
@@ -86,10 +86,14 @@ export default class LinkUtils {
// Hash is 32 hex chars. Path is optional (NomadNet only).
const hashPattern = "[a-fA-F0-9]{32}";
+ // NomadNet paths may include field data after a backtick, e.g.
+ // hash:/page/forum/thread.mu`cat=general|thread=slug
+ // Path charset: URL path chars plus Nomad field separators (` | =).
+ const pathPattern = "/[\\w./?%&=_+~|`-]*";
// Optional prefix, then hash, optional path. Bare hashes with no prefix and no
// path are intentionally skipped to avoid false positives inside URLs.
const reticulumRegex = new RegExp(
- `(nomadnet://|nomadnet@|lxmf://|lxmf@|lxmf:)?(${hashPattern})(?::(/[\\w\\d./?%&=_-]*))?`,
+ `(nomadnet://|nomadnet@|lxmf://|lxmf@|lxmf:)?(${hashPattern})(?::(${pathPattern}))?`,
"g"
);
@@ -102,10 +106,15 @@ export default class LinkUtils {
(prefix && (prefix.startsWith("nomadnet://") || prefix.startsWith("nomadnet@"))) || !!path;
if (isNomadNet) {
- const fullPath = path || defaultNomadPagePath();
+ const { core: pathCore, suffix: pathSuffix } = path
+ ? this.splitTrailingPunctuation(path)
+ : { core: "", suffix: "" };
+ const fullPath = pathCore || defaultNomadPagePath();
const url = `${hash}:${fullPath}`;
const safeAttr = Utils.escapeHtml(url);
- return `<a href="#" class="nomadnet-link text-blue-600 dark:text-blue-400 hover:underline font-mono" data-nomadnet-url="${safeAttr}">${match}</a>`;
+ const labelMatch = path ? `${prefix || ""}${hash}:${fullPath}` : match;
+ const label = Utils.escapeHtml(labelMatch);
+ return `<a href="#" class="nomadnet-link text-blue-600 dark:text-blue-400 hover:underline font-mono" data-nomadnet-url="${safeAttr}">${label}</a>${pathSuffix}`;
} else {
return `<a href="#" class="lxmf-link text-blue-600 dark:text-blue-400 hover:underline font-mono" data-lxmf-address="${hash}">${match}</a>`;
}

diff --git a/tests/frontend/LinkUtils.test.js b/tests/frontend/LinkUtils.test.js
index 01307578..dcafcf68 100644
--- a/tests/frontend/LinkUtils.test.js
+++ b/tests/frontend/LinkUtils.test.js
@@ -24,6 +24,39 @@ describe("LinkUtils.js", () => {
expect(result).toContain('data-nomadnet-url="1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"');
});
+ it("includes Nomad backtick field parameters in the link", () => {
+ const text =
+ "9ce92808be498e9e05590ff27cbfdfe4:/page/forum/thread.mu`cat=general|thread=critical-security-update-rns-139-fixes-severe-rnsh-security-flaw";
+ const result = LinkUtils.renderReticulumLinks(text);
+ expect(result).toContain('class="nomadnet-link');
+ expect(result).toContain(
+ 'data-nomadnet-url="9ce92808be498e9e05590ff27cbfdfe4:/page/forum/thread.mu`cat=general|thread=critical-security-update-rns-139-fixes-severe-rnsh-security-flaw"'
+ );
+ expect(result).toContain(
+ ">9ce92808be498e9e05590ff27cbfdfe4:/page/forum/thread.mu`cat=general|thread=critical-security-update-rns-139-fixes-severe-rnsh-security-flaw</a>"
+ );
+ expect(result).not.toMatch(/thread\.mu<\/a>`cat=/);
+ });
+
+ it("keeps Nomad field params when wrapped with nomadnet:// prefix", () => {
+ const text =
+ "nomadnet://1dfeb0d794963579bd21ac8f153c77a4:/page/forum/thread.mu`cat=general|thread=slug";
+ const result = LinkUtils.renderReticulumLinks(text);
+ expect(result).toContain(
+ 'data-nomadnet-url="1dfeb0d794963579bd21ac8f153c77a4:/page/forum/thread.mu`cat=general|thread=slug"'
+ );
+ });
+
+ it("trims trailing sentence punctuation after Nomad field params", () => {
+ const text =
+ "see 1dfeb0d794963579bd21ac8f153c77a4:/page/forum/thread.mu`cat=general|thread=slug.";
+ const result = LinkUtils.renderReticulumLinks(text);
+ expect(result).toContain(
+ 'data-nomadnet-url="1dfeb0d794963579bd21ac8f153c77a4:/page/forum/thread.mu`cat=general|thread=slug"'
+ );
+ expect(result).toContain("</a>.");
+ });
+
it("does not detect bare hash without prefix as lxmf", () => {
const text = "1dfeb0d794963579bd21ac8f153c77a4";
const result = LinkUtils.renderReticulumLinks(text);

diff --git a/tests/frontend/MarkdownRenderer.test.js b/tests/frontend/MarkdownRenderer.test.js
index fa29c4dc..da3dce02 100644
--- a/tests/frontend/MarkdownRenderer.test.js
+++ b/tests/frontend/MarkdownRenderer.test.js
@@ -193,6 +193,16 @@ describe("MarkdownRenderer.js", () => {
expect(result).toContain("1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu");
});
+ it("keeps Nomad backtick parameters inside conversation links", () => {
+ const text =
+ "read 9ce92808be498e9e05590ff27cbfdfe4:/page/forum/thread.mu`cat=general|thread=critical-security-update-rns-139-fixes-severe-rnsh-security-flaw";
+ const result = MarkdownRenderer.render(text);
+ expect(result).toContain(
+ 'data-nomadnet-url="9ce92808be498e9e05590ff27cbfdfe4:/page/forum/thread.mu`cat=general|thread=critical-security-update-rns-139-fixes-severe-rnsh-security-flaw"'
+ );
+ expect(result).not.toMatch(/thread\.mu<\/a>`cat=/);
+ });
+
it("detects nomadnet:// links with just hash", () => {
const text = "nomadnet://1dfeb0d794963579bd21ac8f153c77a4";
const result = MarkdownRenderer.render(text);


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────